﻿using System;
using Microsoft.SharePoint.Administration;
using System.Xml;
using Microsoft.SharePoint.Utilities;
using System.IO;

namespace SPNotesFor.Administration
{
	/// <summary>
	/// Update the file docicon.xml to add an icon for a specified extension.
	/// </summary>
	sealed class UpdateDocIconJob : SPJobDefinition
	{
		[Persisted]
		private string filename, extension;
		[Persisted]
		private byte[] rawData;


		public UpdateDocIconJob()
		{
		}

		public UpdateDocIconJob(String extension, SPService service, SPServer server, String iconName, byte[] iconData)
			: base(GetName(extension), service, server, SPJobLockType.None)
		{
			this.extension = extension;
			this.filename = iconName;
			this.rawData = iconData;
			this.Title = "Register icon for extension: " + extension;
		}

		public override void Execute(Guid targetInstanceId)
		{
			// First copy the icon file in the Images directory
			String destination = SPUtility.GetGenericSetupPath(@"TEMPLATE\IMAGES\" + this.filename);
			if (File.Exists(destination)) File.Delete(destination);
			File.WriteAllBytes(destination, this.rawData);

			// Update docicon.xml
			String docIconPath = SPUtility.GetGenericSetupPath(@"TEMPLATE\xml\docicon.xml");

			XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
			XmlDocument doc = new XmlDocument();
			bool hasChanges = false, update = false;

			using (XmlReader xmlReader = XmlReader.Create(docIconPath, xmlReaderSettings))
			{
				doc.Load(xmlReader);
				xmlReaderSettings.CloseInput = true;

				// Keep a reference on the SafeControls tag
				XmlNode node = doc.DocumentElement.SelectSingleNode(
					String.Format("/DocIcons/ByExtension/Mapping[@Key='{0}']", this.extension));

				// node not found
				if (node == null)
				{
					node = doc.CreateElement("Mapping");
					XmlAttribute asmAttr = doc.CreateAttribute("Key");
					asmAttr.Value = this.extension;
					node.Attributes.Append(asmAttr);

					asmAttr = doc.CreateAttribute("Value");
					asmAttr.Value = this.filename;
					node.Attributes.Append(asmAttr);

					asmAttr = doc.CreateAttribute("OpenControl");
					asmAttr.Value = String.Empty;
					node.Attributes.Append(asmAttr);

					XmlNode parentNode = doc.DocumentElement.SelectSingleNode("/DocIcons/ByExtension");
					parentNode.AppendChild(node);
					hasChanges = true;
				}
				else
				{
					XmlAttribute attr = node.Attributes["Value"];
					if (attr != null && attr.Value != this.filename)
					{
						attr.Value = this.filename;
						hasChanges = true;
						update = true;
					}
				}
			}

			if (hasChanges)
			{
				XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
				xmlWriterSettings.Indent = true;
				xmlWriterSettings.CloseOutput = true;
				using (XmlWriter writer = XmlWriter.Create(docIconPath, xmlWriterSettings))
					doc.Save(writer);

				if (update)
					SPLog.LogString(@"{0} icon file updated to {1}", this.extension, this.filename);
				else
					SPLog.LogString(@"{0} icon file added in 12\TEMPLATES\xml\docicon.xml", this.extension);
			}
		}

		internal static String GetName(string extension)
		{
			return String.Format("Update docicon.xml for .{0}", extension);
		}
	}
}
